package activities;

import handler.Utilities;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;

import model.Album;
import model.Artist;
import model.Music;
import model.MusicDB;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.Bundle;
import android.os.Handler;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.example.lecteurmp3.R;

/**
 * Player activity
 * @author jean
 *
 */
public class MainActivity extends Activity implements OnCompletionListener, SeekBar.OnSeekBarChangeListener {
	
	// Button
	private ImageButton btnList;
	private ImageButton btnPlay;
	private ImageButton btnPrev;
	private ImageButton btnNext;
	private ImageButton btnShuffle;
	private ImageButton btnRepeat;
	private ImageButton btnLike;
	// Seekbar
	private SeekBar songProgressBar;
	// Player state
	private boolean isShuffle = false;
	private int isRepeat = 0;
	private boolean isEmptySd = false;
	// Label
	private TextView songTitle;
	private TextView songArtistName;
	private TextView songAlbumName;
	private TextView songCurrentDuration;
	private TextView songTotalDuration;
	// AlbumCover
	private ImageView albumCover;
	// MediaPlayer Object
	private MediaPlayer mp;
	// Utility Object
	private Utilities util = new Utilities();
	// Handler
	private Handler mHandler = new Handler();
	// Listening list
	private ArrayList<Music> songsList = new ArrayList<Music>();
	private ArrayList<Music> songsListToPlay;
	private int currentIndexSong = 0;
	// Database parameter
	private MusicDB musicDb;
	// Entity parameter
	private Music currentMusic;
	private Artist currentArtist;
	private Album currentAlbum;
	
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		
		ArrayList<HashMap<String, String>> list = util.getAllFileOnSdCard();
		
		// Verification about SD content
		if(list.size()<=0) { // If it empty
			setContentView(R.layout.warning_message); // set warning view
			isEmptySd = true;
			return;
		}
		
		setContentView(R.layout.player);
		
		// Player Buttons
		btnPlay = (ImageButton) findViewById(R.id.btnPlay);
		btnNext = (ImageButton) findViewById(R.id.btnNext);
		btnPrev = (ImageButton) findViewById(R.id.btnPrev);
		btnRepeat = (ImageButton) findViewById(R.id.btnRepeat);
		btnShuffle = (ImageButton) findViewById(R.id.btnShuffle);
		songProgressBar = (SeekBar) findViewById(R.id.seekbar);
		songTitle = (TextView) findViewById(R.id.songTitle);
		songArtistName = (TextView) findViewById(R.id.songArtist);
		songAlbumName = (TextView) findViewById(R.id.songAlbum);
		albumCover = (ImageView) findViewById(R.id.albumCover);
		songCurrentDuration = (TextView) findViewById(R.id.songCurrentDurationLabel);
		songTotalDuration = (TextView) findViewById(R.id.songTotalDurationLabel);
		btnLike = (ImageButton)findViewById(R.id.btnLike);
		btnList = (ImageButton)findViewById(R.id.btnList);
		
		// Initialization...
		mp = new MediaPlayer();
		songProgressBar.setOnSeekBarChangeListener(this);
		mp.setOnCompletionListener(this);
		musicDb = new MusicDB(this, list);
		musicDb.open();
		
		if(!isEmptySd) {
			/*if(util.checkDataBase(this, "music.db")) {
				Toast.makeText(getApplicationContext(), "existe", Toast.LENGTH_SHORT).show();
			} else {
				Toast.makeText(getApplicationContext(), "existe pas !", Toast.LENGTH_SHORT).show();
			}*/
			musicDb.updateDb();
			
		}
		
		if(util.getIntArrayPref(this, "listening") != null) { // Si une playlist �tait d�j� en �coute avant...
			songsList = musicDb.cursorToMusic(musicDb.getMusicByArrayId(util.getIntArrayPref(this, "listening")));
		}
		else songsList = musicDb.cursorToMusic(musicDb.getAllMusic());
		
		songsListToPlay = new ArrayList<Music>(songsList);
		musicDb.close();
		playSong(false);
		
		
		
		/**
		 * Play button click event
		 * plays a song and changes button to pause image
		 * pauses a song and changes button to play image
		 * */
		btnPlay.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// check for already playing
				if(mp.isPlaying()){
					if(mp!=null){
						mp.pause();
						// Changing button image to play button
						btnPlay.setImageResource(R.drawable.btn_play);
					}
				}else{
					// Resume song
					if(mp!=null){
						mp.start();
						// Changing button image to pause button
						btnPlay.setImageResource(R.drawable.btn_pause);
					}
				}
				
			}
		});
		
		/**
		 * Next button click event
		 * Plays next song by taking currentIndexSongIndex + 1
		 * */
		btnNext.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				// check if next song is there or not
				if(isRepeat == 2) {
					playSong(true);
					return;
				}
				currentIndexSong = (currentIndexSong+1)%songsList.size();
				if(currentIndexSong == 0){ // We back to first song
					songsListToPlay.clear();
					songsListToPlay = new ArrayList<Music>(songsList);
					if(isRepeat == 0) playSong(false);
					else if(isRepeat == 1) playSong(true);
				}else{ // Continue the playlist...
					songsListToPlay.remove(0);
					playSong(true);
				}
			}
		});
		
		/**
		 * Back button click event
		 * Plays previous song by currentIndexSongIndex - 1
		 * */
		btnPrev.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				if(mp.getCurrentPosition() < 5000) {
					if(isRepeat == 2) {
						playSong(true);
						return;
					}
					if(currentIndexSong > 0){
						/*	Si on reviens en arri�re, on r�cup�re la chanson
						 * dans songsList pour la mettre en premier dans 
						 * songsListToPlay
						 */
						songsListToPlay.add(0,songsList.get(currentIndexSong-1));
						currentIndexSong--;
						playSong(true);
					}else{
						// play last song
						/*
						 * Cas particulier, si on est au premier element
						 * et qu'on revient au dernier, alors on charge dans la
						 * playlist tampon uniquement le dernier element.
						 */
						songsListToPlay.clear();
						songsListToPlay.add(songsList.get(songsList.size() - 1));
						currentIndexSong = songsList.size() - 1;
						playSong(true);
					}
				} else {
					playSong(true);
					return;
				}
			}
		});
		
		/**
		 * Button Click event for Repeat button
		 * Enables repeat flag to true
		 * */
		btnRepeat.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				isRepeat = (isRepeat+1)%3;
				if(isRepeat == 0){ // Repeat is OFF
					Toast.makeText(getApplicationContext(), "Repeat is off", Toast.LENGTH_SHORT).show();
					btnRepeat.setImageResource(R.drawable.repeat);
				}else if(isRepeat == 1){ 
					Toast.makeText(getApplicationContext(), "Repeat list is on", Toast.LENGTH_SHORT).show();
					btnRepeat.setImageResource(R.drawable.repeat_hover);
				}else {
					Toast.makeText(getApplicationContext(), "Repeat track is on", Toast.LENGTH_SHORT).show();
					btnRepeat.setImageResource(R.drawable.repeat_hover2);
					isShuffle = false;
					btnShuffle.setImageResource(R.drawable.shuffle);
				}
			}
		});
		
		/**
		 * Button Click event for Shuffle button
		 * Enables shuffle flag to true
		 * */
		btnShuffle.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				if(isShuffle){
					// make shuffle to false
					isShuffle = false;
					musicDb.open();
					if(util.getIntArrayPref(MainActivity.this, "listening") != null) { // Si une playlist �tait d�j� en �coute avant...
						songsList = musicDb.cursorToMusic(musicDb.getMusicByArrayId(util.getIntArrayPref(MainActivity.this, "listening")));
					}
					else songsList = musicDb.cursorToMusic(musicDb.getAllMusic());
					musicDb.close();
					songsListToPlay.clear();
					songsListToPlay = new ArrayList<Music>(songsList);
					Toast.makeText(getApplicationContext(), "Shuffle is off", Toast.LENGTH_SHORT).show();
					btnShuffle.setImageResource(R.drawable.shuffle);
				}else{
					// make shuffle to true
					isShuffle= true;
					songsList = util.toRandomPlaylist(songsList, currentIndexSong);
					currentIndexSong = 0;
					songsListToPlay.clear();
					songsListToPlay = new ArrayList<Music>(songsList);
					Toast.makeText(getApplicationContext(), "Shuffle is on", Toast.LENGTH_SHORT).show();
					// make repeat to false
					if(isRepeat == 2) {
						isRepeat = 0;
						btnRepeat.setImageResource(R.drawable.repeat);
					}
					btnShuffle.setImageResource(R.drawable.shuffle_hover);
				}
			}
		});
		
		/**
		 * Button Click event for Like button
		 * Enables like flag to true
		 * */
		btnLike.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				if(currentMusic.isLike()){
					// make like to false
					musicDb.open();
					musicDb.updateLike(currentMusic.getId(), false);
					songsList.get(currentIndexSong).setLike(false);
					btnLike.setImageResource(R.drawable.like);
					musicDb.close();
				}else{
					// make like to true
					musicDb.open();
					musicDb.updateLike(songsListToPlay.get(0).getId(), true);
					songsList.get(currentIndexSong).setLike(true);
					btnLike.setImageResource(R.drawable.like_hover);
					musicDb.close();
				}
			}
		});
		
		btnList.setOnClickListener(new View.OnClickListener() {
			
			@Override
			public void onClick(View arg0) {
				Intent i = new Intent(getApplicationContext(), MainTabActivity.class);
				startActivityForResult(i, 1000);			
			}
		});
		

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		menu.add(0, 1, 1, "Actualisation pochettes");
		return true;
	}
	
	
	public boolean onOptionsItemSelected(MenuItem item){
		switch(item.getItemId()){
		case 1: musicDb.MAJPochette();
			break;
		}
		return true;
	}
	
	/**
	 * Receiving song index from playlist view
	 * and play the song
	 * */
	@Override
    protected void onActivityResult(int requestCode,
                                     int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if(requestCode == 1000) { // Si �a provient bien de l'activit� MainTabActivity
	        if(resultCode == 100){ // Come from list item
	         	 Bundle extras = data.getExtras();
	         	 boolean b = extras.containsKey("songsList");
	         	 currentIndexSong = extras.getInt("songIndex");
	         	 songsList = extras.getParcelableArrayList("songsList");
	         	 songsListToPlay = util.getSongsToPlay(songsList, currentIndexSong);
	         	 // Store it in SharedPreference
	         	 ArrayList<Integer> list = util.setArrayMusicToArrayInt(songsList);
	         	 util.setIntArrayPref(this,"listening", list);
	         	 // play selected song
	             playSong(true);
	             
	        }else if(resultCode == 10) { // Come from previous button
	        }
        }
 
    }
	
	/**
	 * Background Runnable thread
	 * */
	private Runnable mUpdateTimeTask = new Runnable() {
		private boolean killMe=false;
	   public void run() {
		   if(!killMe) {
			   long totalDuration = mp.getDuration();
			   long currentDuration = mp.getCurrentPosition();
			  
			   // Displaying Total Duration time
			   songTotalDuration.setText(""+util.milliSecondsToTimer(totalDuration));
			   // Displaying time completed playing
			   songCurrentDuration.setText(""+util.milliSecondsToTimer(currentDuration));
			   
			   // Updating progress bar
			   int progress = (int)(util.getProgressPercentage(currentDuration, totalDuration));
			   //Log.d("Progress", ""+progress);
			   songProgressBar.setProgress(progress);
			   
			   // Running this thread after 100 milliseconds
		       mHandler.postDelayed(this, 100);
		   }
	   }
	   
	   public void kill() {
		   killMe = true;
	   }
	};
	
	/**
	 * Update timer on seekbar
	 * */
	public void updateProgressBar() {
        mHandler.postDelayed(mUpdateTimeTask, 100);        
    }

	/**
	 * 
	 * */
	@Override
	public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {
		
	}

	/**
	 * When user starts moving the progress handler
	 * */
	@Override
	public void onStartTrackingTouch(SeekBar seekBar) {
		// remove message Handler from updating progress bar
		mHandler.removeCallbacks(mUpdateTimeTask);
    }

	/**
	 * When user stops moving the progress hanlder
	 * */
	@Override
    public void onStopTrackingTouch(SeekBar seekBar) {
		mHandler.removeCallbacks(mUpdateTimeTask);
		int totalDuration = mp.getDuration();
		int currentPosition = util.progressToTimer(seekBar.getProgress(), totalDuration);
		
		// forward or backward to certain seconds
		mp.seekTo(currentPosition);
		
		// update timer progress again
		updateProgressBar();
    }

	/**
	 * On Song Playing completed
	 * if repeat is ON play same song again
	 * if shuffle is ON play random song
	 * */
	@Override
	public void onCompletion(MediaPlayer arg0) {
		// check if next song is there or not
		if(isRepeat == 2) {
			playSong(true);
			return;
		}
		currentIndexSong = (currentIndexSong+1)%songsList.size();
		if(currentIndexSong == 0){ // We back to first song
			songsListToPlay.clear();
			songsListToPlay = new ArrayList<Music>(songsList);
			if(isRepeat == 0) playSong(false);
			else if(isRepeat == 1) playSong(true);
		}else{ // Continue the playlist...
			songsListToPlay.remove(0);
			playSong(true);
		}
	}
	
	/**
	 * Function to play a song
	 * @param play - start or not the music
	 * */
	public void  playSong(boolean play){
		// Play song
		try {
        	mp.reset();
			mp.setDataSource(songsListToPlay.get(0).getPathName());
			mp.prepare();
			if(play) {
				mp.start();
				// Change btnPause
				btnPlay.setImageResource(R.drawable.btn_pause);
			} else {
				btnPlay.setImageResource(R.drawable.btn_play);
			}
			
			currentMusic = songsListToPlay.get(0);
			
			musicDb.open();
			
			// Displaying Song title, artist, album and picture...
			String title = songsListToPlay.get(0).getTitle();
			currentArtist = musicDb.cursorToArtist(musicDb.getArtist(songsListToPlay.get(0).getIdArtist())).get(0);
			currentAlbum = musicDb.cursorToAlbum(musicDb.getAlbum(songsListToPlay.get(0).getIdAlbum())).get(0);
			songArtistName.setText(currentArtist.getName());
			songAlbumName.setText(currentAlbum.getName());
        	songTitle.setText(title);
        	Bitmap bmp = util.byteToBitmap(currentAlbum.getAlbumCover());
        	if(bmp != null) albumCover.setImageBitmap(bmp);
        	else albumCover.setImageResource(R.drawable.album_cover);
        	
        	if(songsListToPlay.get(0).isLike()) btnLike.setImageResource(R.drawable.like_hover);
        	else btnLike.setImageResource(R.drawable.like);
        	
        	// +1 to nbPlay...
        	musicDb.updateNbplay(songsListToPlay.get(0).getId(), songsListToPlay.get(0).getNbPlay());
			
        	musicDb.close();
        	
			// set Progress bar values
			songProgressBar.setProgress(0);
			songProgressBar.setMax(100);
			
			// Updating progress bar
			updateProgressBar();			
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (IllegalStateException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	@Override
	 public void onPause(){
		super.onPause();
		//Toast.makeText(getApplicationContext(), "onPause...", Toast.LENGTH_SHORT).show();
	 }
	
	@Override
	 public void onResume(){
		super.onResume();
		//Toast.makeText(getApplicationContext(), "onResume...", Toast.LENGTH_SHORT).show();
	 }
	
	@Override
	 public void onRestart(){
		super.onRestart();
		//Toast.makeText(getApplicationContext(), "onRestart...", Toast.LENGTH_SHORT).show();
	 }
	
	@Override
	 public void onStop(){
		super.onStop();
		//Toast.makeText(getApplicationContext(), "onStop...", Toast.LENGTH_SHORT).show();
	 }
	
	@Override
	 public void onDestroy(){
		super.onDestroy();
		//Toast.makeText(getApplicationContext(), "onDestroy...", Toast.LENGTH_SHORT).show();
	    mp.release();
	    mHandler.removeCallbacks(mUpdateTimeTask);
	 }

}
